<?php


include_once 'CodeObject.php';
include_once 'TypeReferenceCollection.php';
include_once 'CommentStatementCollection.php';
include_once 'TypeMemberCollection.php';
include_once 'Attributes.php';


/**
 * The TypeDeclaration class represents a type declaration 
 * for a class or an interface.
 * 
 * TypeDeclaration extends the CodeObject abstract class.
 * 
 * @package UC_PHPCodeModel
 * @author Uros Calakovic
 */

class TypeDeclaration extends CodeObject
{
    /**
     * The constructor sets the class / interface name
     * and initializes members to empty collections of the appropriate type.
     * 
     * @param string $name The name of the class / interface to be created
     */
    
    public function __construct($name)
    {
        parent::__construct();

        $this->set_name($name);
        
        $this->BaseTypes = new TypeReferenceCollection();
        $this->Members = new TypeMemberCollection();
    }
    
    /**
     * Used for making private / protected variables 
     * accessible from outside the class.
     * 
     * @param string $name Name of the field to be accessed
     * @param mixed $value The value the field should be set to, usually a collection.
     * @see CodeObject::__set()
     */
    
    public function __set($name, $value)
    {
        parent::__set($name, $value);
        
        if($name == 'BaseTypes')
        {
            $this->set_BaseTypes($value);
        }
        
        if($name == 'Members')
        {
            $this->set_Members($value);
        }
    }
    
    /**
     * Used for making private / protected variables 
     * accessible from outside the class.
     * 
     * @param string $name Name of the field to be accessed
     * @return mixed The field that $name specified, usually a collection
     * @see CodeObject::__get()
     */
    
    public function __get($name)
    {
        $ret = parent::__get($name);
        
        if($ret != null)
        {
            return $ret;
        }
        
        if($name == 'BaseTypes')
        {
            return $this->get_BaseTypes();
        }
        
        if($name = 'Members')
        {
            return $this->get_Members();
        }
    }
    
    /**
     * The $BaseTypes getter method.
     * 
     * @return TypeReferenceCollection 
     */
    
    public function get_BaseTypes()
    {
        return $this->BaseTypes;
    }

    /**
     * The $BaseTypes setter method.
     * 
     * @param TypeReferenceCollection $BaseTypes 
     */
    
    public function set_BaseTypes(TypeReferenceCollection $BaseTypes)
    {
        $this->BaseTypes = $BaseTypes;
    }

    /**
     * The $Members getter method.
     * 
     * @return TypeMemberCollection 
     */
    
    public function get_Members()
    {
        return $this->Members;
    }

    /**
     * The $Members setter method.
     * 
     * @param TypeMemberCollection $Members 
     */
    
    public function set_Members(TypeMemberCollection $Members)
    {
        $this->Members = $Members;
    }

    /**
     * The $isClass getter method.
     * 
     * @return bool
     */
    
    public function get_isClass()
    {
        return $this->isClass;
    }
    
    /**
     * The $isClass setter method.
     * 
     * $isClass and $isInterface are mutually exclusive.
     * 
     * @param bool $isClass 
     * 
     * @assert (123) throws InvalidArgumentException 
     * @assert ('name') throws InvalidArgumentException 
     */

    public function set_isClass($isClass)
    {
        if(is_bool($isClass))
        {
            $this->isClass = $isClass;
            $this->isInterface = !$isClass;
        }
        else
        {
            throw new InvalidArgumentException(
                'The value must be boolean.');
        }
    }

    /**
     * The $isInterface getter method.
     * 
     * @return bool 
     */
    
    public function get_isInterface()
    {
        return $this->isInterface;
    }

    /**
     * The $isInterface setter method.
     * 
     * $isClass and $isInterface are mutually exclusive.
     * 
     * @param bool $isInterface 
     * 
     * @assert (123) throws InvalidArgumentException 
     * @assert ('name') throws InvalidArgumentException 
     */
    
    public function set_isInterface($isInterface)
    {
        if(is_bool($isInterface))
        {
            $this->isInterface = $isInterface;
            $this->isClass = !$isInterface;
        }
        else
        {
            throw new InvalidArgumentException(
                'The value must be boolean.');
        }
    }

    /**
     *  The $name getter method.
     * 
     * @return string
     */
    
    public function get_name()
    {
        return $this->name;
    }

    /**
     * The $name settor method.
     * 
     * set_name() only checks if $name is a string.
     * Whether TypeDeclaration name is a valid class / interface name
     * is checked by PHPCodeGenerator.
     * 
     * @param string $name 
     * 
     * @assert (123) throws InvalidArgumentException 
     * @assert (true) throws InvalidArgumentException 
     */
    
    public function set_name($name)
    {
        if(is_string($name))
        {
            $this->name = $name;
        }
        else
        {
            throw new InvalidArgumentException(
                'The value must be a string.');
        }
    }

    /**
     * A collection of TypeReference instances that represent 
     * classes and interfaces this object extends or implements.
     * 
     * @var TypeReferenceCollection
     */
    
    private $BaseTypes;
    
    /**
     * A collection of TypeMember instances that represent
     * class / interface members that this object contains.
     * 
     * @var TypeMemberCollection
     */
    
    private $Members;    
    
    /**
     * Wheter this object is a class.
     * 
     * @var bool
     */
    
    private $isClass = true;
    
    /**
     * Whether this object is an interface.
     * 
     * @var bool
     */
    
    private $isInterface = false;
    
    /**
     * The name of this object.
     * 
     * @var string
     */
    
    private $name;
}

?>
